package jsp.classes;

import java.util.ArrayList;
import jpa.JPAConnection;
import jpa.entities.Employee;
import jpa.entities.Item;
import jpa.entities.ItemType;
import jpa.entities.Project;
import jpa.entities.Task;

/**
 * @author Remco Haszing
 * @author Aymeric Blok
 */
public class Session {

    // properties
    private JPAConnection jpa;
    private boolean loggedIn;
    private Employee user;
    private String uploadDir;
    private Cache cache;

    // getters
    /**
     * @return The JPA connection used for writing data to the database.
     */
    public JPAConnection getJPAConnection() {
        return this.jpa;
    }

    /**
     * @return Wether or not the user has logged in succesfully.
     */
    public boolean isLoggedIn() {
        return this.loggedIn;
    }

    /**
     * @return The Employee as which the user has logged in.
     */
    public Employee getEmployee() {
        return this.user;
    }

    /**
     * @return The directory where uploaded files are stored.
     */
    public String getUploadDir() {
        return this.uploadDir;
    }

    // methods
    /**
     * Verifies the password of the user trying to log in. This method checks if
     * the combination of the set username and password exists in the database.
     * The password itself is not stored and it never should be for security
     * reasons.
     *
     * @param username The username to verify.
     * @param password The password to verify.
     * @return True if the log in was succesful, otherwise false.
     */
    public boolean logIn(String username, String password) {
        try {
            this.jpa = new JPAConnection("BaalzebubPU");
            this.user = this.jpa.getUserByUsername(username, password);
            this.loggedIn = this.user != null;
            this.uploadDir = System.getProperty("catalina.home") + "/upload/";
            this.cache = new Cache();
            return this.loggedIn;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Returns the project with the requested id. This method searches for a
     * project this user is member of that has the requested id number. If this
     * project exists it will be cached and returned. Otherwise null is
     * returned.
     *
     * @param id The id of the project to search.
     * @return The project with the corresponding id number.
     */
    public Project findProjectById(long id) {
        Project o = this.cache.getProjectById(id);
        if (o == null) {
            for (Project p : this.user.getProjects()) {
                if (p.getId() == id) {
                    this.cache.cache(p);
                    return p;
                }
            }
        }
        return o;
    }

    /**
     * Returns the Employee with the requested id.
     *
     * @param id The id of the employee to search.
     * @return The Employee with the corresponding id number.
     */
    public Employee findEmployeeById(long id) {
        for (Employee e : this.jpa.getAllUsers()) {
            if (e.getId() == id) {
                return e;
            }
        }
        return null;
    }

    /**
     * Returns the task with the matching id. This method finds and returns the
     * task with the requested id.
     *
     * @param id The id number of the task to find.
     * @return The task with the mathing id number.
     */
    public Task findTaskById(long id) {
        for (Task t : this.user.getTasks()) {
            if (t.getId() == id) {
                return t;
            }
        }
        return null;
    }

    /**
     * Returns the item with the requested itemId. This method searches for the
     * item with the requested itemId in the project with the requested
     * projectId. If no such item is found, null is returned.
     *
     * @param projectId The id number of the project to search.
     * @param itemId The id number of the item to find.
     * @return The requested item.
     */
    public Item findProjectItemById(long projectId, long itemId) {
        Item i = this.cache.getItemById(itemId);
        if (i == null) {
            i = this.findProjectById(projectId).findItemById(itemId);
            if (i != null) {
                this.cache.cache(i);
            }
        }
        return i;
    }

    /**
     * Returns an HTML tree structure containing all items of a project. This
     * method returns a String representing an HMTL tree structure containing
     * all items in the project.
     *
     * @param folder The folder to search in. This should be null to get the
     * entire folder structure.
     * @param projectId The id number of the project to search in.
     * @return An HTML tree structure containing all items of a project.
     */
    public String getItems(Item folder, long projectId) {
        String html = "<dl";
        if (folder == null) {
            folder = this.findProjectById(projectId).getRootFolder();
            html += " class=\"itemFolder\"";
        } else {
            html += " class=\"item\"";
        }
        html += ">";
        for (Item i : folder.getChildren()) {
            if (i.getType() == ItemType.FOLDER) {
                html += "<dt class=\"itemFolder\">";
            } else {
                html += "<dt class=\"item\">";
            }
            html += i.getType() == ItemType.FOLDER ? "<a class=\"expandable\">+</a>" : "<span>-</span>";
            html += "<a href=\"javascript:selectItem(" + i.getId() + "," + projectId + ")\">" + i.getTitle() + " " + i.getType() + "</a>";
            if (i.getType() == ItemType.FOLDER) {
                html += getItems(i, projectId);
            }
            html += "</dt>";
        }
        html += "</dl>";
        return html;
    }
    
    public ArrayList<Item> listOfItems(Project project) {
        ArrayList<Item> list = new ArrayList<Item>();
        project.getRootFolder().addSubItemsToList(list);
        return list;
    }
}
